﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Foundation.Collections;
using Windows.UI.Xaml.Data;

namespace Application4
{
    public class ObservableVector<T> : Collection<T>, INotifyPropertyChanged, IObservableVector<T>
    {
        // *** Constants ***

        private const string PropertyNameCount = "Count";
        private const string PropertyNameIndexer = "Item[]";

        // *** Events ***

        public event PropertyChangedEventHandler PropertyChanged;
        public event VectorChangedEventHandler<T> VectorChanged;

        // *** Constructors ***

        public ObservableVector()
            : base()
        {
        }

        public ObservableVector(IList<T> list)
            : base(list)
        {
        }

        // *** Protected Methods ***   

        protected override void ClearItems()
        {
            base.ClearItems();
            OnPropertyChanged(PropertyNameCount);
            OnPropertyChanged(PropertyNameIndexer);
            OnVectorChanged(CollectionChange.Reset, 0);
        }

        protected override void InsertItem(int index, T item)
        {
            base.InsertItem(index, item);
            OnPropertyChanged(PropertyNameCount);
            OnPropertyChanged(PropertyNameIndexer);
            OnVectorChanged(CollectionChange.ItemInserted, (uint)index);
        }

        protected override void RemoveItem(int index)
        {
            base.RemoveItem(index);
            OnPropertyChanged(PropertyNameCount);
            OnPropertyChanged(PropertyNameIndexer);
            OnVectorChanged(CollectionChange.ItemRemoved, (uint)index);
        }

        protected override void SetItem(int index, T item)
        {
            base.SetItem(index, item);
            OnPropertyChanged(PropertyNameIndexer);
            OnVectorChanged(CollectionChange.ItemChanged, (uint)index);
        }

        protected void OnPropertyChanged(string propertyName)
        {
            OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
        }

        protected void OnVectorChanged(CollectionChange collectionChange, uint index)
        {
            OnVectorChanged(new VectorChangedEventArgs(collectionChange, index));
        }

        // *** Event Handlers ***

        protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, e);
        }

        protected virtual void OnVectorChanged(IVectorChangedEventArgs e)
        {
            if (VectorChanged != null)
                VectorChanged(this, e);
        }

        // *** Private Sub-classes ***

        private class VectorChangedEventArgs : IVectorChangedEventArgs
        {
            // *** Fields ***

            private readonly CollectionChange collectionChange;
            private readonly uint index;

            // *** Constructors ***

            public VectorChangedEventArgs(CollectionChange collectionChange, uint index)
            {
                this.collectionChange = collectionChange;
                this.index = index;
            }

            // *** Properties ***

            public CollectionChange CollectionChange
            {
                get
                {
                    return collectionChange;
                }
            }

            public uint Index
            {
                get
                {
                    return index;
                }
            }
        }
    }
}
